-
Notifications
You must be signed in to change notification settings - Fork 2
Changed: major NLP refactoring for flexibility and significantly improve performance #171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
`JuMP.operator` expects a different signature for the gradient when the function is univariate.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #171 +/- ##
==========================================
+ Coverage 98.81% 98.85% +0.04%
==========================================
Files 25 25
Lines 4034 4118 +84
==========================================
+ Hits 3986 4071 +85
+ Misses 48 47 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…raints The splatting syntax of `JuMP` forces use to compute the Jacobians of the inequality and equality constraints as a multiple gradients (concatenated in the Jacobian matrices). This means that `jacobian!` function of the AD tools were called redundantly `ng` and `neq` times, for a specific decision vector value `Z̃`. This is wasteful. A caching mechanism was implemented to store the Jacobians of the constraints and reuse them when needed. The performance improvement is about 5-10x faster now on `NonLinMPC` with `NonLinModel`.
Very cool, good work!! |
@baggepinnen, did you noticed a performance regression between Julia 1.11 and 1.10? If I compare the nonlinear benchmarks of our paper on both version with Julia btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(446.673 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(134.010 ms)
btime_NMPC_regul_solver_IP = median(bm) = TrialEstimate(387.229 ms)
btime_NMPC_regul_solver_IP2 = median(bm) = TrialEstimate(160.588 ms)
btime_EMPC_track_solver_IP = median(bm) = TrialEstimate(466.283 ms)
btime_EMPC_track_solver_IP2 = median(bm) = TrialEstimate(151.958 ms)
btime_EMPC_regul_solver_IP = median(bm) = TrialEstimate(464.341 ms)
btime_EMPC_regul_solver_IP2 = median(bm) = TrialEstimate(139.097 ms)
btime_SLMPC_track_solver_AS = median(bm) = TrialEstimate(6.457 ms)
btime_SLMPC_regul_solver_AS = median(bm) = TrialEstimate(5.967 ms) Julia btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(630.590 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(163.150 ms)
btime_NMPC_regul_solver_IP = median(bm) = TrialEstimate(560.399 ms)
btime_NMPC_regul_solver_IP2 = median(bm) = TrialEstimate(185.831 ms)
btime_EMPC_track_solver_IP = median(bm) = TrialEstimate(648.639 ms)
btime_EMPC_track_solver_IP2 = median(bm) = TrialEstimate(177.418 ms)
btime_EMPC_regul_solver_IP = median(bm) = TrialEstimate(691.486 ms)
btime_EMPC_regul_solver_IP2 = median(bm) = TrialEstimate(189.661 ms)
btime_SLMPC_track_solver_AS = median(bm) = TrialEstimate(7.322 ms)
btime_SLMPC_regul_solver_AS = median(bm) = TrialEstimate(7.413 ms) Julia btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(626.744 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(156.591 ms)
btime_NMPC_regul_solver_IP = median(bm) = TrialEstimate(446.302 ms)
btime_NMPC_regul_solver_IP2 = median(bm) = TrialEstimate(147.617 ms)
btime_EMPC_track_solver_IP = median(bm) = TrialEstimate(654.216 ms)
btime_EMPC_track_solver_IP2 = median(bm) = TrialEstimate(171.278 ms)
btime_EMPC_regul_solver_IP = median(bm) = TrialEstimate(628.532 ms)
btime_EMPC_regul_solver_IP2 = median(bm) = TrialEstimate(181.976 ms)
btime_SLMPC_track_solver_AS = median(bm) = TrialEstimate(7.223 ms)
btime_SLMPC_regul_solver_AS = median(bm) = TrialEstimate(7.057 ms) Should I raise an issue on julia's github? |
I did not, if raising an issue, it would probably be good to narrow down slightly where the slowdown can have appeared? Are all installed dependencies the same in both cases? If not, the slowdown could be in one of them? |
Ok good news ! I ran the benchmarks once more on the new release (v1.11.4), and now the differences with v1.10 is quite small, e.g. the first 2 tests gives (IP is Ipopt, IP2 is MadNLP): btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(457.770 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(128.249 ms) I did not had the time to run them all but this is encouraging 🚀 edit: here's all the results. Some a a bit faster, some are a bit slower, but nothing problematic anymore IMO btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(457.770 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(128.249 ms)
btime_NMPC_regul_solver_IP = median(bm) = TrialEstimate(425.197 ms)
btime_NMPC_regul_solver_IP2 = median(bm) = TrialEstimate(143.778 ms)
btime_EMPC_track_solver_IP = median(bm) = TrialEstimate(457.981 ms)
btime_EMPC_track_solver_IP2 = median(bm) = TrialEstimate(137.837 ms)
btime_EMPC_regul_solver_IP = median(bm) = TrialEstimate(499.611 ms)
btime_EMPC_regul_solver_IP2 = median(bm) = TrialEstimate(147.623 ms)
btime_SLMPC_track_solver_AS = median(bm) = TrialEstimate(5.662 ms)
btime_SLMPC_regul_solver_AS = median(bm) = TrialEstimate(5.624 ms) |
First improvement
One big step further toward integration of
DifferentiationInterface.jl
Related to #162
Second improvement
The splatting syntax of
JuMP
forces us to compute the Jacobians of the constraints as a combination of multiple gradients (concatenated as a Jacobian).This means that the
jacobian
function of the AD tool (denseForwardDiff.jl
, for now) were called redundantlyng
andneq
times for a specific decision vector valueZ̃
(whereng
andneq
is the respective number of nonlinear inequality and equality constraints). This is wasteful. A caching mechanism was implemented to store the Jacobians of the constraints and reuse them when needed.The performance improvement is about 5-10x faster now on
NonLinMPC
withNonLinModel
. Note that it only applies when nonlinear constraints are present (i.e.: output or state constraint of nonlinear plant model, custom constraint and multiple shooting of nonlinear plant model)FYI @baggepinnen and @1-Bart-1, will release it soon today or tomorrow.
edit : just tested this branch on the pendulum model. Now
MultipleShooting
is only 1.6x slower than theSingleShooting
transcription (it was more than 5x times slower before), so it's plenty fast enough for real time! I'm really proud of this improvement 🍾🎉🍾 🎉. The additional gains will be using sparse differentiation withDifferentionInterface.jl
.